package cn.kys.common.utils;

import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.feature.type.Name;

import java.io.File;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ShpWriter {


    public static void createPointShp(List<Map> list, String targetFilePath) {
        try {
            File file = new File(targetFilePath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(CRS.decode("EPSG:4326"));
            tb.setName("shapefile");

            tb.add("id", Integer.class);
            tb.add("createtime", String.class);
            tb.add("username", String.class);
            tb.add("taskname", String.class);
            tb.add("userid", Integer.class);
            tb.add("taskid", Integer.class);
            tb.add("subtaskid", Integer.class);
            tb.add("nickname", String.class);
            tb.add("lon", Double.class);
            tb.add("lat", Double.class);
            tb.add("the_geom", Point.class);

            ds.createSchema(tb.buildFeatureType());
            ds.setCharset(Charset.forName("UTF-8"));
//            ds.setCharset(Charset.forName("GBK"));
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer =
                    ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
            //写入数据

            for (Map map1 : list) {
                String lonString = (String) map1.get("lon");
                String latString = (String) map1.get("lat");
                SimpleFeature feature = writer.next();

                if (lonString.isEmpty() || latString.isEmpty()) {
                    continue;
                }
                feature.setAttribute("the_geom", new GeometryFactory().createPoint(new Coordinate(Double.parseDouble(map1.get("lon").toString()), Double.parseDouble(map1.get("lat").toString()))));
                //id, create_time, username, taskname, userid, taskid, subtaskid, lat, lon, nickname
                feature.setAttribute("id", map1.get("id"));
                feature.setAttribute("createtime", map1.get("createtime"));
                feature.setAttribute("username", map1.get("username"));
                feature.setAttribute("taskname", map1.get("taskname"));
                feature.setAttribute("userid", map1.get("userid"));
                feature.setAttribute("taskid", map1.get("taskid"));
                feature.setAttribute("subtaskid", map1.get("subtaskid"));
                feature.setAttribute("nickname", map1.get("nickname"));
                feature.setAttribute("lon", map1.get("lon"));
                feature.setAttribute("lat", map1.get("lat"));
                writer.write();
            }
        writer.close();
        ds.dispose();
    } catch(
    Exception e)

    {
        e.printStackTrace();
    }

}

    public static void createLineShp(List<Map> list, String targetFilePath) {
        try {
            File file = new File(targetFilePath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);

            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(CRS.decode("EPSG:4326"));
            tb.setName("shapefile");

            tb.add("id", Integer.class);
            // 添加其他属性（与原有代码保持不变）

            // 修改为线要素类型
            tb.add("the_geom", LineString.class);
            tb.add("lon", Double.class);
            tb.add("lat", Double.class);

            ds.createSchema(tb.buildFeatureType());
            ds.setCharset(Charset.forName("UTF-8"));
            ds.setCharset(Charset.forName("GBK"));

            // 设置Writer
            SimpleFeatureType sft = ds.getSchema();
            GeometryDescriptor geomDesc = sft.getGeometryDescriptor();
            Name geomName = geomDesc.getName();
            Coordinate prevCoordinate = null;

            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(sft);
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

            // 写入数据
            for (Map map1 : list) {
                // 获取经纬度坐标
                String lonString = (String) map1.get("lon");
                String latString = (String) map1.get("lat");

                if (lonString.isEmpty() || latString.isEmpty()) {
                    continue;
                }

                // 设置要素属性
                SimpleFeature feature = writer.next();
                // 设置其他属性（与原有代码保持不变）
                feature.setAttribute("lon", map1.get("lon"));
                feature.setAttribute("lat", map1.get("lat"));

                // 构建线要素
                Coordinate coordinate = new Coordinate(Double.parseDouble(lonString), Double.parseDouble(latString));
                GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
                if (prevCoordinate != null) {
                    LineString line = geometryFactory.createLineString(new Coordinate[]{prevCoordinate, coordinate});
                    feature.setAttribute("the_geom", line);
                }
                prevCoordinate = coordinate;

                // 将要素写入文件
                writer.write();
            }

            writer.close();
            ds.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void WriteVectorFile(List list, String strVectorFile) {

        // 注册所有的驱动
        ogr.RegisterAll();

        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        //gdal.SetConfigOption("SHAPE_ENCODING", "");
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
        //创建数据，这里以创建ESRI的shp文件为例
        String strDriverName = "ESRI Shapefile";
        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName);

        if (oDriver == null) {
            System.out.println(strVectorFile + " 驱动不可用！\n");
            return;
        }

        // 创建数据源
        DataSource oDS = oDriver.CreateDataSource(strVectorFile, null);
        if (oDS == null) {
            System.out.println("创建矢量文件【" + strVectorFile + "】失败！\n");
            return;
        }
        SpatialReference srs = new SpatialReference();
        srs.ImportFromEPSG(4326);

        // 创建图层，创建一个多边形图层，这里没有指定空间参考，如果需要的话，需要在这里进行指定
        Layer oLayer = oDS.CreateLayer("TestPolygon", srs, ogr.wkbPoint, null);
        if (oLayer == null) {
            System.out.println("图层创建失败！\n");
            return;
        }

        // 下面创建属性表
        // 先创建一个叫FieldID的整型属性
        FieldDefn latField = new FieldDefn("lat", ogr.OFTString);
        oLayer.CreateField(latField, 1);


        FieldDefn lonField = new FieldDefn("lon", ogr.OFTString);
        oLayer.CreateField(lonField, 1);


        FeatureDefn oDefn = oLayer.GetLayerDefn();

        for (int i = 0; i < list.size(); i++) {

            String lat = ((Map) list.get(i)).get("lat").toString();
            String lon = ((Map) list.get(i)).get("lon").toString();
            String wkt = "POINT(" + lon + " " + lat + ")";
            Feature feature = new Feature(oDefn);
            feature.SetField(0, lat);
            feature.SetField(1, lon);


            Geometry geom = Geometry.CreateFromWkt(wkt);
            feature.SetGeometry(geom);

            oLayer.CreateFeature(feature);
        }


        oDS.FlushCache();
        System.out.println("\n数据集创建完成！\n");
    }

    public static void WriteVectorLineFile(List list, String strVectorFile) {

        // 注册所有的驱动
        ogr.RegisterAll();

        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        //gdal.SetConfigOption("SHAPE_ENCODING", "");
        gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
        //创建数据，这里以创建ESRI的shp文件为例
        String strDriverName = "ESRI Shapefile";
        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName);

        if (oDriver == null) {
            System.out.println(strVectorFile + " 驱动不可用！\n");
            return;
        }

        // 创建数据源
        DataSource oDS = oDriver.CreateDataSource(strVectorFile, null);
        if (oDS == null) {
            System.out.println("创建矢量文件【" + strVectorFile + "】失败！\n");
            return;
        }
        SpatialReference srs = new SpatialReference();
        srs.ImportFromEPSG(4326);

        // 创建图层，创建一个多边形图层，这里没有指定空间参考，如果需要的话，需要在这里进行指定
        Layer oLayer = oDS.CreateLayer("TestPolygon", srs, ogr.wkbLineString, null);
        if (oLayer == null) {
            System.out.println("图层创建失败！\n");
            return;
        }

        // 下面创建属性表
        // 先创建一个叫FieldID的整型属性


        FeatureDefn oDefn = oLayer.GetLayerDefn();

        String lineStr = "";
        for (int i = 0; i < list.size(); i++) {

            String lat = ((Map) list.get(i)).get("lat").toString();
            String lon = ((Map) list.get(i)).get("lon").toString();

            if ("".equals(lat)) {
                lineStr = lineStr;
            } else {
                lineStr = lineStr + lon + " " + lat + ",";
            }
        }
        lineStr = lineStr.substring(0, lineStr.length() - 1);
        String wkt = "LINESTRING(" + lineStr + ")";
        Feature feature = new Feature(oDefn);
        Geometry geom = Geometry.CreateFromWkt(wkt);
        feature.SetGeometry(geom);

        oLayer.CreateFeature(feature);
        oDS.FlushCache();
        System.out.println("\n数据集创建完成！\n");
    }

    public static void WriteVectorFile(String polygon, String strVectorFile) {

        // 注册所有的驱动
        ogr.RegisterAll();

        // 为了支持中文路径，请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文，请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "");

        //创建数据，这里以创建ESRI的shp文件为例
        String strDriverName = "ESRI Shapefile";
        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName);

        if (oDriver == null) {
            System.out.println(strVectorFile + " 驱动不可用！\n");
            return;
        }

        // 创建数据源
        DataSource oDS = oDriver.CreateDataSource(strVectorFile, null);
        if (oDS == null) {
            System.out.println("创建矢量文件【" + strVectorFile + "】失败！\n");
            return;
        }
        SpatialReference srs = new SpatialReference();
        srs.ImportFromEPSG(4326);

        // 创建图层，创建一个多边形图层，这里没有指定空间参考，如果需要的话，需要在这里进行指定
        //Layer oLayer =oDS.CreateLayer("TestPolygon", srs, ogr.wkbMultiPolygon, null);
        Layer oLayer = oDS.CreateLayer("TestPolygon", srs, ogr.wkbPolygon, null);
        if (oLayer == null) {
            System.out.println("图层创建失败！\n");
            return;
        }

        FeatureDefn oDefn = oLayer.GetLayerDefn();

        // 下面创建属性表
        // 先创建一个叫FieldID的整型属性
        FieldDefn gid = new FieldDefn("gid", ogr.OFTInteger);
        oLayer.CreateField(gid, 1);

        Feature feature = new Feature(oDefn);
        feature.SetField(0, 1);

        String wkt = "POLYGON((" + polygon + "))";

        //String wkt = "POLYGON ((75.1440237561685 37.996318647375,75.1440259391014 37.9962957187398,75.1441439321652 37.9961764985077,75.1434884233068 37.9957823422256,75.142467198021 37.9950681243005,75.1420397642378 37.9947080487656,75.1419930250974 37.9946505306955,75.1412130853368 37.9947945756507,75.1429870270856 37.9964374587142,75.1430823742169 37.9963805772956,75.1434100153384 37.9961782715839,75.1434990809488 37.9961621384503,75.1436205880399 37.9961683985713,75.1437583836722 37.9962195066363,75.1439326770199 37.9962962082926,75.1440237561685 37.996318647375))";
        Geometry geom = Geometry.CreateFromWkt(wkt);
        feature.SetGeometry(geom);

        oLayer.CreateFeature(feature);

        oDS.FlushCache();
        System.out.println("\n数据集创建完成！\n");
    }
}
